package io.renren.utils;

import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.Map;

/**
 * Created by Yorke on 2016/10/18.
 */
public class FreeMarkerUtils {
    private static Logger logger = LoggerFactory.getLogger(FreeMarkerUtils.class);


    /**
     * 根据模板生成文件内容.
     *
     * @param templateFilePath the template file name
     * @param root             the root
     * @return
     */
    public static String generateByTemplate(String templateFilePath, Map root) throws Exception {

        // 所有的模板都放在template模板下

        String filecontent = readTemplateFile(templateFilePath);

        String templateText = generateByTemplate(filecontent, root, null);

        return templateText;
    }

    /**
     * 根据模板生成文件内容.
     *
     * @param templateFilePath the template file name
     * @param root             the root
     * @return
     */
    public static String generateByTemplate(String templateFilePath, Map root, String outFilePath, String outFilename) throws Exception {

        FileBaseUtil.createFilePath(outFilePath);

        String filecontent = readTemplateFile(templateFilePath);
        return generateByTemplate(filecontent, root, outFilePath + File.separator + outFilename);
    }

    /**
     * 根据模板生成文件内容.
     *
     * @param filecontent 模板内容
     * @param root        the root
     * @return
     */
    public static String generateByTemplate(String filecontent, Map root, String outFilePath) throws Exception {

        String templateText = null;
        Writer out = null;
        try {
            Configuration cfg = new Configuration();
            StringTemplateLoader stringLoader = new StringTemplateLoader();


            stringLoader.putTemplate("Template", filecontent);
            cfg.setTemplateLoader(stringLoader);
            Template temp = cfg.getTemplate("Template", "utf-8");
            /* 创建数据模型 */
            out = new StringWriter(2048);
            if (outFilePath != null) {
                out = new OutputStreamWriter(new FileOutputStream(outFilePath), "UTF-8");
                temp.process(root, out);
            } else {
                temp.process(root, out);
                templateText = out.toString();
            }

        } catch (IOException e) {
            logger.error("generateByTemplate IOException error! ", e);
            throw new RuntimeException(e);
        } catch (TemplateException e) {
            logger.error("generateByTemplate TemplateException error! ", e);
            throw new RuntimeException(e);
        } catch (Exception e) {
            logger.error("generateByTemplate Exception error! ", e);
            throw new RuntimeException(e);
        } finally {
            if (out != null) {
                // out.flush();
                out.close();
            }
        }

        return templateText;
    }


    public static String getSystemPath() {
        try {
            String path = System.getProperty("user.dir") + "/";
            logger.info("getSystemPath path: {}", path);
            return path;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 以文件流的方式读取文件，springboot只能这样才能都去到jar的里面的文件
     *
     * @param resourcesfilepath 传递resources目录下的文件路径，springboot用
     *                          the filepath
     * @return the string
     * @version
     */
    public static String readTemplateFile(String resourcesfilepath) {
        InputStreamReader reader = null;
        BufferedReader bufferedReader = null;
        String content = null;
        try {


            //先查看外部是否配置了ftl文件，如果优先使用外部的

            String outfiletemplatepath = getSystemPath() + resourcesfilepath;
            outfiletemplatepath = outfiletemplatepath.replace("//", "/");
            logger.info("readFileByInputStream read file from out file, outfiletemplatepath: {}", outfiletemplatepath);

            File file = new File(outfiletemplatepath);

            if (file.isFile() && file.exists()) { // 判断文件是否存在
                content = readFileByLines(new FileInputStream(file));
                logger.info("readFileByInputStream read file from out file, template: {}", content);
            } else {
                logger.info("readFileByLines read file from out file, can not find file ");
            }

            if (!StringUtils.isEmpty(content)) {
                return content;
            }

            //外部没得，使用内部resource目录下的ftl文件
            logger.info("readFileByInputStream read file from resources, resourcesfilepath: {}", resourcesfilepath);
            Resource source = new ClassPathResource(resourcesfilepath);

            content = readFileByLines(source.getInputStream());

            logger.info("readFileByInputStream read file  from resources, template: {}", content);

            //如果都没的，报错


        } catch (IOException e) {
            logger.error("readFileByLines error!", e);
        }
        return content;
    }

    /**
     * 以行为单位读取文件，常用于读面向行的格式化文件
     * @param inputStream inputStream
     * @return the string
     * @version
     */
    public static String readFileByLines(InputStream inputStream) {
        InputStreamReader reader = null;
        BufferedReader bufferedReader = null;
        String text = "";
        try {

            String code = "utf-8";
            String tempString = null;
            reader = new InputStreamReader(inputStream, code);// 考虑到编码格式
            bufferedReader = new BufferedReader(reader);
            // 一次读入一行，直到读入null为文件结束
            String lineSeparator = System.getProperty("line.separator", "\n");
            while ((tempString = bufferedReader.readLine()) != null) {
                text = text + tempString + lineSeparator.toString();
            }

            if (text.lastIndexOf(lineSeparator.toString()) != -1) {
                text = text.substring(0, text.lastIndexOf(lineSeparator.toString()));
            }

        } catch (IOException e) {
            logger.error("readFileByLines error!", e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    logger.error("readFileByLines reader.close() error!", e);
                }
            }

            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    logger.error("readFileByLines bufferedReader.close() error!", e);
                }
            }
        }
        return text;
    }


}
